﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing.Design;
using System.Windows.Forms.Design;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using Microsoft.VisualStudio.Modeling;
using VsxFactory.Modeling.VisualStudio;
using System.ComponentModel;
using Microsoft.VisualStudio.Modeling.Diagrams;
using VsxFactory.Modeling;

namespace VsxFactory.Modeling.VisualStudio
{
    /// <summary>
    /// Editeur permettant de sélectionner un template visual studio
    /// </summary>
    public abstract class ComboBoxTypeEditor : UITypeEditor
    {
        private ListBox _comboBox;
        private IWindowsFormsEditorService _edSvc;

        /// <summary>
        /// Gets the editor style used by the <see cref="M:System.Drawing.Design.UITypeEditor.EditValue(System.IServiceProvider,System.Object)"></see> method.
        /// </summary>
        /// <param name="context">An <see cref="T:System.ComponentModel.ITypeDescriptorContext"></see> that can be used to gain additional context information.</param>
        /// <returns>
        /// A <see cref="T:System.Drawing.Design.UITypeEditorEditStyle"></see> value that indicates the style of editor used by the <see cref="M:System.Drawing.Design.UITypeEditor.EditValue(System.IServiceProvider,System.Object)"></see> method. If the <see cref="T:System.Drawing.Design.UITypeEditor"></see> does not support this method, then <see cref="M:System.Drawing.Design.UITypeEditor.GetEditStyle"></see> will return <see cref="F:System.Drawing.Design.UITypeEditorEditStyle.None"></see>.
        /// </returns>
        public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
        {
            return UITypeEditorEditStyle.Modal;
        }

        /// <summary>
        /// Edits the value.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="sp">The sp.</param>
        /// <param name="value">The value.</param>
        /// <returns></returns>
        public override object EditValue(ITypeDescriptorContext context, IServiceProvider sp, object value)
        {
            _edSvc = (IWindowsFormsEditorService)sp.GetService(typeof(IWindowsFormsEditorService));
            if (_edSvc != null)
            {
                _comboBox = new ListBox();
                List<string> values = GetValues(context.Instance);
                if (values != null)
                {
                    int maxSize = PopulateListBoxItems(values);
                    if (_comboBox.Items.Count == 0)
                        return value;

                    _comboBox.Size = new Size(maxSize + 10, 120);
                    _comboBox.KeyDown += KeyDown;
                    _comboBox.Leave += ValueChanged;
                    _comboBox.DoubleClick += ValueChanged;
                    _comboBox.Click += ValueChanged;
                    _edSvc.DropDownControl(_comboBox);

                    if (_comboBox.SelectedItem != null)
                        return _comboBox.SelectedItem.ToString();
                }
            }
            return value;
        }

        public abstract List<string> GetValues(object obj);

        /// <summary>
        /// Populates the list box items.
        /// </summary>
        /// <param name="list">The list.</param>
        /// <returns></returns>
        private int PopulateListBoxItems(List<string> list)
        {
            int maxSize = 0;
            using (Graphics graphics = _comboBox.CreateGraphics())
            {
                Font font = _comboBox.Font;
                foreach (string item in list)
                {
                    _comboBox.Items.Add(item);
                    SizeF ef = graphics.MeasureString(item, font);
                    int num = (int)ef.Width;
                    if (num > maxSize)
                    {
                        maxSize = num;
                    }
                }
            }
            return maxSize;
        }

        /// <summary>
        /// Keys down.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.Forms.KeyEventArgs"/> instance containing the event data.</param>
        private void KeyDown(object sender, KeyEventArgs e)
        {
            if (((e != null) && e.Control) && ((e.KeyCode == Keys.Return) && (_edSvc != null)))
            {
                _edSvc.CloseDropDown();
            }
        }

        /// <summary>
        /// Values the changed.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void ValueChanged(object sender, EventArgs e)
        {
            if (_edSvc != null)
            {
                _edSvc.CloseDropDown();
            }
        }
    }
}
